« powrót

SharePoint Foundation 2010 - Utworzenie listy z danych zewnętrznych MsSql z wykorzystaniem Business Data Connectivity Service i External Content Type

Opublikowano: 2011-05-04 , wyświetlono: 14516

Wstęp

By przybliżyć Bdc w SharePoint Foundation 2010, przedstawię swój pierwszy projekt, który tworzyłem by zapoznać się z tym rozwi±zaniem. Była to integracja danych z systemu ewidencji sprzętu komputerowego Ewida z SharePiont Foundation 2010 poprzez zewnętrzn± listę z wykorzystaniem Business Data Connectivity Service i External Content Type.

Krótki plan czynno¶ci jakie były do zrobienia

i po kolei ich realizacja

Stworzenie odpowiedniego widoku w bazie danych Ewida

Najpierw zabrałem się do tworzenia widoku, który zawierałby wszystkie potrzebne mi dane. Po pobieżnym zapoznaniu się ze struktur± bazy, która przechowuje informacje o sprzęcie i użytkownikach, utworzyłem dwa widoki.

Pierwszy to cała lista sprzętu i jego użytkowników, tutaj pozbyłem się już ewentualnych warto¶ci null, które mogły by póĽniej sprawić kłopot SharePoint'owi

create view HardwareList as
select 
  s.C_TKey as KeyID,
  isnull(s.C_InventoryNr, '') as NrEwid,
  isnull(s.C_Manufacturer, '') as Producent,
  isnull(s.C_Model, '') as Model,
  isnull(s.C_Name, '') as Typ,
  isnull(s.C_SerialNr, '') as Sn,
  isnull(s.C_Status, '') as Stan,
  isnull(u.C_LastName, '') as Nazwisko,
  isnull(u.C_FirstName, '') as Imie,
  isnull(u.C_Department, '') as Dzial,
  isnull(u.C_Location, '') as Lokalizacja,
  isnull(u.C_RoomNr, '') as NrPokoju,
  isnull(u.C_Position, '') as Stanowisko,
  isnull(u.C_PhoneWork, '') as Telefon,
  isnull(s.C_HostName, '') as NetNazwa
from 
  T_ECSuite s
  left join T_ECUser u on (s.C_ParentGuid = u.C_GuidCode)

I drugi na bazie pierwszego, który prezentuje tylko komputery i notebook'i będ±ce w użyciu

create view HardwareList_ComputersInUse] as
select *
  from HardwareList
  where
    Stan = 'w użyciu'
    and Typ in ('KOMPUTER', 'NOTEBOOK')

Utworzenie w Visual Studio 2010 projektu BDC Model

Po uruchomieniu VS2010 z szablonów SharePoint 2010 wybieramy BDC Model, następnie podajemy adres url serwera SharePoint i zaznaczamy Deploy as farm solution.
Visual Studio wybór typu projektu

Zdefiniowanie klasy przechowuj±cej element listy

Zmieniamy nazwy utworzonych w projekcie klas Entity1.cs na Workstation.cs i Entity1Service.cs na WorkstationService.cs oraz ewentualnie innych, np. namespace'ów (ja u siebie tak zrobiłem) Klasa Workstation odpowiada za element listy i musi mieć zdefiniowane odpowiednie atrybuty. Dla zdefiniowanego przeze mnie widoku kod klasy przedstawia się następuj±co

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BdcDemo.BdcModelEwida
{
    /// <summary>
    /// This class contains the properties for Entity1. The properties keep the data for Entity1.
    /// If you want to rename the class, don't forget to rename the entity in the model xml as well.
    /// </summary>
    public partial class Workstation
    {
        public int KeyID { get; set; }
        public string NrEwid { get; set; }
        public string Producent { get; set; }
        public string Model { get; set; }
        public string Typ { get; set; }
        public string Sn { get; set; }
        public string Stan { get; set; }
        public string Nazwisko { get; set; }
        public string Imie { get; set; }
        public string Dzial { get; set; }
        public string Lokalizacja { get; set; }
        public string NrPokoju { get; set; }
        public string Stanowisko { get; set; }
        public string Telefon { get; set; }
        public string NetNazwa { get; set; }
    }
}

Zmiana w modelu BDC atrybutów zgodnie z wcze¶niej utworzon± klas±

Zgodnie ze zdefiniowan± klas±, trzeba w odpowiedni sposób zmienić utworzony przez kreatora model BDC.
Zmieniamy Entity1 na Workstation, jako identyfikator wybieramy KeyID (jest KONIECZNY unikalny identyfikator dla listy) i jego typ ustawiamy na System.Int32. Następnie zmieniamy i dodajemy nowe parametry dla modelu zgodnie z wcze¶niej zdefiniowanymi atrybutami klasy (Add Type Descriptor). Wykonać to należy dla obu metod ReadList oraz ReadItem.

Dla ReadItem jako zwracany parametr ustawiamy Workstation, natomiast dla ReadList WorkstationList (wg poniższych zrzutów ekranu)



Zaimplementowanie testowych metod ReadList, ReadItem w celu sprawdzenia rozwi±zania.

Przystępujemy teraz do pracy na pliku WorkstationService.cs, modyfikuj±c metody ReadList i ReadItem by dawały jakie¶ warto¶ci bez komunikacji z baz± danych by sprawdzić tylko poprawno¶ć modelu i wdrażania rozwi±zania do ¶rodowiska SharePoint. Utworzyłem dodatkowe prywatne metody do odczytu elementy i listy z przedrostkiem skeleton by upro¶cić testowanie i nie używać potem bloków zakomentowanego kodu. Poniżej pełny kod Ľródłowy klasy.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BdcDemo.BdcModelEwida
{
    /// <summary>
    /// All the methods for retrieving, updating and deleting data are implemented in this class file.
    /// The samples below show the finder and specific finder method for Workstation.
    /// </summary>
    public partial class WorkstationService
    {
        /// <summary>
        /// This is a sample specific finder method for Workstation.
        /// If you want to delete or rename the method think about changing the xml 
        /// in the BDC model file as well.
        /// </summary>
        /// <param name="id"></param>
        /// <returns>Workstation</returns>
        public static Workstation ReadItem(int id)
        {
            return (skeletonReadItem(id));
        }

        /// <summary>
        /// walkthrough skeleton
        /// - return example Worksation object
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private static Workstation skeletonReadItem(int id)
        {
            Workstation wk = new Workstation();

            wk.KeyID = 1;
            wk.NrEwid = "1234-PK";
            wk.Producent = "HP";
            wk.Model = "Model";
            wk.Typ = "Typ";
            wk.Sn = "Sn-1234";
            wk.Stan = "w uzyciu";
            wk.Nazwisko = "Nowak";
            wk.Imie = "Jan";
            wk.Dzial = "KA";
            wk.Lokalizacja = "But";
            wk.NrPokoju = "411";
            wk.Stanowisko = "referent";
            wk.Telefon = "14-14";
            wk.NetNazwa = "KA_REF";
            
            return (wk);
        }

        /// <summary>
        /// This is a sample finder method for Workstation.
        /// If you want to delete or rename the method think about changing the xml
        /// in the BDC model file as well.
        /// </summary>
        /// <returns>IEnumerable of Entities</returns>
        public static IEnumerable<Workstation> ReadList()
        {
            return (skeletonReadList());
        }

        /// <summary>
        /// walkthrough skeleton
        /// - add one element to list
        /// </summary>
        /// <returns></returns>
        private static IEnumerable<Workstation> skeletonReadList()
        {
            Workstation[] workstations = new Workstation[1];
            Workstation wk = new Workstation();
            wk.KeyID = 21743;
            wk.NrEwid = "pk-987";
            wk.Producent = "Dell";
            wk.Model = "Model";
            wk.Typ = "Typ";
            wk.Sn = "Sn-1234";
            wk.Stan = "w uzyciu";
            wk.Nazwisko = "Nowak";
            wk.Imie = "Jan";
            wk.Dzial = "KA";
            wk.Lokalizacja = "But";
            wk.NrPokoju = "411";
            wk.Stanowisko = "referent";
            wk.Telefon = "14-14";
            wk.NetNazwa = "KA_REF";

            workstations[0] = wk;

            return (workstations);
        }
    }
}

Zmodyfikowanie projektu do automatycznego deployment'u (dla Foundation)

W zwi±zku z tym, że w Foundation nie ma automatycznego wdrażania rozwi±zania z poziomu Visual Studio 2010, skorzystałem z rozwi±zania opisanego tutaj. Wymaga to pobrania kodu i dodanie Feature Event Receiver.

Jest jeszcze jedno, o wiele prostsze, lecz trzeba mieć zainstalowanego SharePointa (przynajmniej w wersji testowej) by dysponować plikiem Microsoft.Office.SharePoint.ClientExtensions.dll, opisane tutaj

Po tej operacji możliwe automatyczne wdrożenie rozwi±zania dla SharePoint Foundation i model powinien być widoczny na li¶cie, któr± znajdziemy w Central Administration -> Application Management -> Manage service applications -> Business Data Connectivity Service

Konieczne jest jeszcze nadanie uprawnień do usługi BDC dla wszystkich zalogowanych użytkowników oraz rozszerzonych dla Administratora site'a.

Utworzenie nowej listy bazuj±cej na BDC>

Końcowy etap to utworzenie listy przedstawiaj±cej nasze dane.
W witrynie

I w witrynie powinna być dostępna nowa lista zawieraj±ca pola modelu i dane testowe, które zostały wcze¶niej okre¶lone w kodzie. Listę można oczywi¶cie zmodyfikować jak inne do swoich potrzeb.

Zast±pienie metod testowych rzeczywistym odczytem danych

I to w zasadzie jest kompletny opis rozwi±zania opartego na BDC Sernice. By urealnić dane przedstawiane w li¶cie poniżej pełen kod klasy WorkstationService uzupełniony o komunikację z baza danych.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Data.SqlTypes;

namespace BdcDemo.BdcModelEwida
{
    /// <summary>
    /// All the methods for retrieving, updating and deleting data are implemented in this class file.
    /// The samples below show the finder and specific finder method for Workstation.
    /// </summary>
    public partial class WorkstationService
    {
        static SqlConnection getSqlConnection()
        {
            string connStr = "Data Source=dbserver;User ID=user;Password=password; Initial Catalog=DBInventory";
            SqlConnection sqlConn = new SqlConnection(connStr);
            return (sqlConn);
        }

        /// <summary>
        /// This is a sample specific finder method for Workstation.
        /// If you want to delete or rename the method think about changing the xml 
        /// in the BDC model file as well.
        /// </summary>
        /// <param name="id"></param>
        /// <returns>Workstation</returns>
        public static Workstation ReadItem(int id)
        {
            // return (skeletonReadItem(id));
            return (sqlReadItem(id));
        }

        /// <summary>
        /// walkthrough skeleton
        /// - return example Worksation object
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private static Workstation skeletonReadItem(int id)
        {
            Workstation wk = new Workstation();

            wk.KeyID = 1;
            wk.NrEwid = "1234-PK";
            wk.Producent = "HP";
            wk.Model = "Model";
            wk.Typ = "Typ";
            wk.Sn = "Sn-1234";
            wk.Stan = "w uzyciu";
            wk.Nazwisko = "Nowak";
            wk.Imie = "Jan";
            wk.Dzial = "KA";
            wk.Lokalizacja = "But";
            wk.NrPokoju = "411";
            wk.Stanowisko = "referent";
            wk.Telefon = "14-14";
            wk.NetNazwa = "KA_REF";
            
            return (wk);
        }

        /// <summary>
        /// return Workstation object from database
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>        
        private static Workstation sqlReadItem(int id)
        {
            Workstation wk = new Workstation();
            SqlConnection sqlConn = getSqlConnection();
            sqlConn.Open();
            SqlCommand cmd = new SqlCommand();

            cmd.CommandText =
                "SELECT KeyID, NrEwid, Producent, Model, Typ, Sn, Stan, Nazwisko, Imie, " +
                " Dzial, Lokalizacja, NrPokoju, Stanowisko, Telefon, NetNazwa " +
                "FROM HardwareList_ComputersInUse " +
                "WHERE KeyID=" + id.ToString();
            cmd.Connection = sqlConn;

            SqlDataReader reader = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
            if (reader.Read())
            {
                wk.KeyID = reader.GetInt32(0);
                wk.NrEwid = reader.GetString(1);
                wk.Producent = reader.GetString(2);
                wk.Model = reader.GetString(3);
                wk.Typ = reader.GetString(4);
                wk.Sn = reader.GetString(5);
                wk.Stan = reader.GetString(6);
                wk.Nazwisko = reader.GetString(7);
                wk.Imie = reader.GetString(8);
                wk.Dzial = reader.GetString(9);
                wk.Lokalizacja = reader.GetString(10);
                wk.NrPokoju = reader.GetString(11);
                wk.Stanowisko = reader.GetString(12);
                wk.Telefon = reader.GetString(13);
                wk.NetNazwa = reader.GetString(14);
            }
            else
            {
                wk.KeyID = -1;
                wk.NrEwid = "Not found";
                wk.Producent = "";
            }
            reader.Close();
            sqlConn.Dispose();

            return (wk);
        }

        /// <summary>
        /// This is a sample finder method for Workstation.
        /// If you want to delete or rename the method think about changing the xml
        /// in the BDC model file as well.
        /// </summary>
        /// <returns>IEnumerable of Entities</returns>
        public static IEnumerable<Workstation> ReadList()
        {
            // return (skeletonReadList());
            return (sqlReadList());
        }

        /// <summary>
        /// walkthrough skeleton
        /// - add one element to list
        /// </summary>
        /// <returns></returns>
        private static IEnumerable<Workstation> skeletonReadList()
        {
            Workstation[] workstations = new Workstation[1];
            Workstation wk = new Workstation();
            wk.KeyID = 21743;
            wk.NrEwid = "pk-987";
            wk.Producent = "Dell";
            wk.Model = "Model";
            wk.Typ = "Typ";
            wk.Sn = "Sn-1234";
            wk.Stan = "w uzyciu";
            wk.Nazwisko = "Nowak";
            wk.Imie = "Jan";
            wk.Dzial = "KA";
            wk.Lokalizacja = "But";
            wk.NrPokoju = "411";
            wk.Stanowisko = "referent";
            wk.Telefon = "14-14";
            wk.NetNazwa = "KA_REF";

            workstations[0] = wk;

            return (workstations);
        }

        /// <summary>
        /// read list from real sql database
        /// </summary>
        /// <returns></returns>
        private static IEnumerable<Workstation> sqlReadList()
        {
            SqlConnection sqlConn = getSqlConnection();

            try
            {
                List<Workstation> allWorkstations = new List<Workstation>();
                sqlConn.Open();
                SqlCommand cmd = new SqlCommand();

                cmd.CommandText =
                    "SELECT KeyID, NrEwid, Producent, Model, Typ, Sn, Stan, Nazwisko, Imie, " +
                    " Dzial, Lokalizacja, NrPokoju, Stanowisko, Telefon, NetNazwa " +
                    "FROM HardwareList_ComputersInUse ORDER BY KeyID";
                cmd.Connection = sqlConn;

                SqlDataReader reader = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        Workstation wk = new Workstation();
                        wk.KeyID = reader.GetInt32(0);
                        wk.NrEwid = reader.GetString(1);
                        wk.Producent = reader.GetString(2);
                        wk.Model = reader.GetString(3);
                        wk.Typ = reader.GetString(4);
                        wk.Sn = reader.GetString(5);
                        wk.Stan = reader.GetString(6);
                        wk.Nazwisko = reader.GetString(7);
                        wk.Imie = reader.GetString(8);
                        wk.Dzial = reader.GetString(9);
                        wk.Lokalizacja = reader.GetString(10);
                        wk.NrPokoju = reader.GetString(11);
                        wk.Stanowisko = reader.GetString(12);
                        wk.Telefon = reader.GetString(13);
                        wk.NetNazwa = reader.GetString(14);
                        allWorkstations.Add(wk);
                    }
                }
                reader.Close();

                Workstation[] workstations = new Workstation[allWorkstations.Count];
                for (int i = 0; i < allWorkstations.Count; i++)
                    workstations[i] = allWorkstations[i];

                return (workstations);
            }
            catch (Exception e)
            {
                Workstation[] workstations = new Workstation[1];
                Workstation wk = new Workstation();
                wk.KeyID = -1;
                wk.Nazwisko = "Unable to retrieve data";
                wk.Producent = e.Message;
                workstations[0] = wk;

                return (workstations);
            }
            finally
            {
                sqlConn.Dispose();
            }
        }
    }
}



Komentarze: